﻿using PBO.Data;
using PBO.Data.Domain;
using PBO.Data.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace PBO.Forms.DataForm
{
    public partial class FrmExpertEditor : Form
    {

        #region Instance

        private static FrmExpertEditor instance;

        public static FrmExpertEditor GetInstance()
        {
            if (instance == null || instance.IsDisposed)
                instance = new FrmExpertEditor();
            return instance;
        }

        public static FrmExpertEditor GetInstance(PokemonCustomInfo info)
        {
            instance = GetInstance();
            instance.Bind(info);
            return instance;
        }

        #endregion

        private PokemonData data;
        private PokemonCustomInfo info;

        private FrmExpertEditor()
        {
            InitializeComponent();
            this.Icon = Properties.Resources.PokemonBall;
            GetEvControls().ToList().ForEach(n => n.ValueChanged += nudEV_ValueChanged);
            GetIvControls().ToList().ForEach(n => n.ValueChanged += nudEV_ValueChanged);
        }

        private void Bind(PokemonCustomInfo info)
        {
            this.data = GameService.GetPokemon(info.Identity);
            this.info = info;
            Bind(this.data);

            cboNature.SelectedIndex = (int)info.Nature;
            cboAbility.SelectedValue = info.Ability;
            if (cboGender.Items.Count > 1)
            {
                cboGender.SelectedIndex = info.Gender == PokemonGender.Male ? 0 : 1;
            }

            SetEv(info.Ev);
            SetIv(info.Iv);
            var sum = GetEvControls().Sum(n => n.Value);
            lblEVRest.Text = (510 - sum).ToString();
        }

        private void Bind(PokemonData data)
        {
            cboAbility.DataSource = data.Abilities.ToArray();
            cboAbility.DisplayMember = "Name";
            cboAbility.ValueMember = "Trait";
     
            cboGender.DataSource = data.Genders.Select(g => g.ToString()).ToArray();
        }

        #region stat

        private IEnumerable<NumericUpDown> GetEvControls()
        {
            yield return nudHPEV;
            yield return nudAtkEV;
            yield return nudDefEV;
            yield return nudSpeedEV;
            yield return nudSAtkEV;
            yield return nudSDefEV;
        }

        private IEnumerable<NumericUpDown> GetIvControls()
        {
            yield return nudHPIV;
            yield return nudAtkIV;
            yield return nudDefIV;
            yield return nudSpeedIV;
            yield return nudSAtkIV;
            yield return nudSDefIV;
        }

        private BaseStats GetEv()
        {
            var stat = new BaseStats();
            var arr = GetEvControls().Select(n => n.Value).ToArray();
            for (int i = 0; i < 6; i++)
            {
                stat[i] = (int)arr[i];
            }
            return stat;
        }

        private BaseStats GetIv()
        {
            var stat = new BaseStats();
            var arr = GetIvControls().Select(n => n.Value).ToArray();
            for (int i = 0; i < 6; i++)
            {
                stat[i] = (int)arr[i];
            }
            return stat;
        }

        private void SetEv(BaseStats stats)
        {
            var arr = GetEvControls().ToArray();
            for (int i = 0; i < 6; i++)
            {
                arr[i].Value = stats[i];
            }
        }

        private void SetIv(BaseStats stats)
        {
            var arr = GetIvControls().ToArray();
            for (int i = 0; i < 6; i++)
            {
                arr[i].Value = stats[i];
            }
        }

        private void nudEV_ValueChanged(object sender, EventArgs e)
        {
            var arr = GetEvControls().Select(c => c.Name).ToArray();
            var arr2 = GetIvControls().Select(c => c.Name).ToArray();

            var nud = (NumericUpDown)sender;
            var sum = GetEvControls().Sum(n => n.Value);
            if (sum > 510) nud.Value -= sum - 510;
            lblEVRest.Text = Math.Max(0, 510 - sum).ToString();

            var nature = (PokemonNature)cboNature.SelectedIndex;
            var stats = CalculateHelper.GetBaseValue(nature, data.BaseStats, GetIv(), GetEv(), info.LV);
            BindBaseStat(stats);
        }

        private void BindBaseStat(IStats stats)
        {
            lblHPVal.Text = stats.Hp.ToString();
            lblAtkVal.Text = stats.Atk.ToString();
            lblDefVal.Text = stats.Def.ToString();
            lblSpeedVal.Text = stats.Speed.ToString();
            lblSAtkVal.Text = stats.SpAtk.ToString();
            lblSDefVal.Text = stats.SpDef.ToString();
        }

        #endregion

        #region button

        private void cmdClear_Click(object sender, EventArgs e)
        {
            GetEvControls().ToList().ForEach(ev => ev.Value = 0);
        }

        private void cmdOK_Click(object sender, EventArgs e)
        {
            info.Iv.SetValue(GetIv());
            info.Ev.SetValue(GetEv());
            info.Nature = (PokemonNature)cboNature.SelectedIndex;
            info.Ability = GetAbility();
            info.Gender = data.Genders.ElementAt(cboGender.SelectedIndex);
            this.Close();
        }

        private void cmdCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion

        private Trait GetAbility()
        {
            return (Trait)(cboAbility.SelectedValue);
        }

        private void cboAbility_SelectedIndexChanged(object sender, EventArgs e)
        {
            //string move = PokemonValidator.CheckTrait(data.Id, GetAbility(), info.Moves);

            //if (move.Length > 0)
            //{
            //    MessageBox.Show(string.Format("{0} 与 {1} 特性无法共存!", move, cboAbility.SelectedText), "错误", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //}
        }
    }
}